<script setup lang="ts">
import { computed, nextTick, ref, watch } from 'vue';
import { fetchGetLogList, fetchGetLoggerList } from '@/service/api/system-manage';
import { fetchOnlineNodes } from '@/service/api/node';

// 优化类型定义
interface NodeInfo {
  ip: string;
  port: string | number;
}

interface LogEntry {
  message: string;
  timestamp: string;
  level: 'INFO' | 'WARN' | 'ERROR' | 'DEBUG';
  traceId: string;
  loggerName: string;
  threadName: string;
  stackTrace?: string;
  className?: string;
  methodName?: string;
  lineNumber?: number;
}

// 状态定义
const logs = ref<LogEntry[]>([]);
const logContainer = ref<HTMLElement | null>(null);
const modalLog = ref<LogEntry | null>(null);
const showModal = ref(false);
const levelFilter = ref('');
const loggerFilter = ref<string[]>([]);
const keywordFilter = ref<string[]>([]);
const loggerOptions = ref<string[]>([]);
const nodeOptions = ref<NodeInfo[]>([]);
const nodeFilter = ref('');
const startTime = ref('');
const endTime = ref('');

// 获取节点列表
const fetchNodes = async () => {
  try {
    const res = await fetchOnlineNodes();
    nodeOptions.value = res?.data || [];
  } catch {
    nodeOptions.value = [];
  }
};

fetchNodes();

// 获取Logger列表
const fetchLoggers = async () => {
  try {
    const response = nodeFilter.value
      ? await fetchGetLoggerList({ ...parseNodeFilter(nodeFilter.value) })
      : await fetchGetLoggerList();

    loggerOptions.value = response?.data || [];
  } catch (error) {
    console.error('获取Logger列表失败:', error);
    loggerOptions.value = [];
  }
};

fetchLoggers();

// 解析节点筛选器值
function parseNodeFilter(filterValue: string): { nodeIp: string; nodePort: string } {
  const [ip, port] = filterValue.split(':');
  // 确保port是字符串类型
  return { nodeIp: ip, nodePort: port.toString() };
}

// 优化简单的工具函数为箭头函数
const getLogTime = (log: LogEntry | null) => log?.timestamp || '';
const getLogLevel = (log: LogEntry | null) => log?.level || 'INFO';
const getLogClass = (log: LogEntry | null) => log?.loggerName || '';
const getLogContent = (log: LogEntry | null) => log?.message || '';

// 获取日志级别对应的CSS类
const getLevelClass = (log: LogEntry | null) => {
  const level = getLogLevel(log);
  return {
    'level-info': level === 'INFO',
    'level-warn': level === 'WARN',
    'level-error': level === 'ERROR',
    'level-debug': level === 'DEBUG'
  };
};

// 获取日志项对应的CSS类
const getLogItemClass = (log: LogEntry | null) => {
  const level = getLogLevel(log);
  return {
    'log-item-info': level === 'INFO',
    'log-item-warn': level === 'WARN',
    'log-item-error': level === 'ERROR',
    'log-item-debug': level === 'DEBUG'
  };
};

// 获取日志列表函数
const fetchLogList = async () => {
  if (!nodeFilter.value) {
    window.$message?.warning('请先选择节点');
    return;
  }

  try {
    const { nodeIp, nodePort } = parseNodeFilter(nodeFilter.value);
    const params: any = {
      nodeIp,
      nodePort,
      limit: 1000
    };

    // 条件添加参数
    Object.entries({
      level: levelFilter.value,
      logger: loggerFilter.value.length > 0 ? loggerFilter.value.join(',') : '',
      keyword: keywordFilter.value.length > 0 ? keywordFilter.value.join(',') : '',
      startTime: startTime.value,
      endTime: endTime.value
    }).forEach(([key, value]) => {
      if (value) params[key] = value;
    });

    const response = await fetchGetLogList(params);

    if (response?.data?.logs && Array.isArray(response.data.logs)) {
      logs.value = response.data.logs;
      await nextTick();
      scrollToLatestLog();
    } else {
      console.error('日志数据格式不正确:', response);
      logs.value = [];
    }
  } catch (error: any) {
    window.$message?.error(error?.message || '获取日志失败');
    logs.value = [];
  }
};

// 监听筛选条件变化
watch([levelFilter, loggerFilter, keywordFilter, nodeFilter, startTime, endTime], fetchLogList, { deep: true });

// 监听节点选择变化，重新获取logger列表
watch(nodeFilter, fetchLoggers, { immediate: false });

// 清空所有筛选条件
const clearFilters = () => {
  levelFilter.value = '';
  loggerFilter.value = [];
  keywordFilter.value = [];
  startTime.value = '';
  endTime.value = '';
};

// 计算属性 - 过滤后的日志
const filteredLogs = computed(() => logs.value || []);

// 监听日志变化，滚动到顶部
watch(filteredLogs, () => {
  nextTick(() => {
    if (logContainer.value) {
      logContainer.value.scrollTop = 0;
    }
  });
});

// 处理日志点击事件
const handleLogClick = (log: LogEntry) => {
  showModal.value = true;
  modalLog.value = log;
};

// 滚动到最新日志
function scrollToLatestLog() {
  if (logContainer.value) {
    logContainer.value.scrollTop = 0;
  }
}

// 安全解码日志内容
const safeDecodeLogContent = (content: string) => {
  try {
    return decodeURIComponent(decodeURIComponent(content));
  } catch {
    return content;
  }
};
</script>

<template>
  <div class="log-page-wrapper">
    <!-- 筛选条件区域 - 固定在顶部 -->
    <div class="filter-section-fixed">
      <div class="filter-row">
        <ASelect v-model:value="nodeFilter" placeholder="节点选择" class="node-select" allow-clear>
          <ASelectOption
            v-for="node in nodeOptions"
            :key="`${node.ip}:${node.port}`"
            :value="`${node.ip}:${node.port}`"
          >
            {{ `${node.ip}:${node.port}` }}
          </ASelectOption>
        </ASelect>
        <ASelect v-model:value="levelFilter" placeholder="日志级别" class="level-select" allow-clear>
          <ASelectOption value="">全部</ASelectOption>
          <ASelectOption value="INFO">INFO</ASelectOption>
          <ASelectOption value="WARN">WARN</ASelectOption>
          <ASelectOption value="ERROR">ERROR</ASelectOption>
          <ASelectOption value="DEBUG">DEBUG</ASelectOption>
        </ASelect>
        <ASelect
          v-model:value="loggerFilter"
          placeholder="Logger过滤"
          class="logger-select"
          mode="multiple"
          allow-clear
        >
          <ASelectOption v-for="logger in loggerOptions" :key="logger" :value="logger">
            {{ logger.split('.').pop() || logger }}
          </ASelectOption>
        </ASelect>
        <ASelect
          v-model:value="keywordFilter"
          placeholder="关键词搜索"
          class="keyword-select"
          mode="tags"
          allow-clear
          :options="[]"
        />
      </div>
      <div class="filter-row">
        <ADatePicker
          v-model:value="startTime"
          placeholder="开始时间"
          class="date-picker"
          show-time
          format="YYYY-MM-DD HH:mm:ss"
          value-format="YYYY-MM-DD HH:mm:ss"
          allow-clear
        />
        <ADatePicker
          v-model:value="endTime"
          placeholder="结束时间"
          class="date-picker"
          show-time
          format="YYYY-MM-DD HH:mm:ss"
          value-format="YYYY-MM-DD HH:mm:ss"
          allow-clear
        />
        <div class="filter-actions">
          <AButton type="primary" size="small" @click="fetchLogList">刷新</AButton>
          <AButton size="small" @click="clearFilters">清空</AButton>
        </div>
      </div>
    </div>

    <div class="log-management-container h-full p-8px">
      <!-- 日志内容卡片 -->
      <ACard class="log-card-container">
        <!-- 日志内容区域 -->
        <div ref="logContainer" class="log-container h-full">
          <div
            v-for="(log, index) in filteredLogs"
            :key="index"
            class="log-item"
            :class="getLogItemClass(log)"
            @dblclick="handleLogClick(log)"
          >
            <span class="log-time">[{{ getLogTime(log) }}]</span>
            <span class="log-level" :class="getLevelClass(log)">[{{ getLogLevel(log) }}]</span>
            <span class="log-class">
              {{ (log.loggerName || getLogClass(log)).split('.').pop() || log.loggerName || getLogClass(log) }} -
            </span>
            <span class="log-content">{{ safeDecodeLogContent(getLogContent(log)) }}</span>
          </div>
        </div>
      </ACard>

      <!-- 日志详情弹窗 -->
      <AModal v-model:open="showModal" title="日志详情" :footer="null" width="60%" @cancel="showModal = false">
        <div class="modal-log-detail">
          <div class="modal-log-row">
            <span class="modal-log-label">时间：</span>
            <span class="modal-log-value">{{ modalLog?.timestamp || '' }}</span>
          </div>
          <div class="modal-log-row">
            <span class="modal-log-label">级别：</span>
            <span class="modal-log-value level-tag" :class="getLevelClass(modalLog)">{{ modalLog?.level || '' }}</span>
          </div>
          <div class="modal-log-row">
            <span class="modal-log-label">Logger：</span>
            <span class="modal-log-value">
              {{ (modalLog?.loggerName || '').split('.').pop() || modalLog?.loggerName || '' }}
            </span>
          </div>
          <div v-if="modalLog?.className || modalLog?.methodName || modalLog?.lineNumber" class="modal-log-row">
            <span class="modal-log-label">位置：</span>
            <span class="modal-log-value modal-log-location">
              <span v-if="modalLog?.className" class="location-class">{{ modalLog.className.split('.').pop() }}</span>
              <span v-if="modalLog?.methodName" class="location-method">.{{ modalLog.methodName }}()</span>
              <span v-if="modalLog?.lineNumber" class="location-line">:{{ modalLog.lineNumber }}</span>
            </span>
          </div>
          <div class="modal-log-row">
            <span class="modal-log-label">内容：</span>
            <pre class="modal-log-content">{{ modalLog?.message || '' }}</pre>
          </div>
          <div v-if="modalLog?.stackTrace && modalLog?.level === 'ERROR'" class="modal-log-row">
            <span class="modal-log-label">堆栈：</span>
            <pre class="modal-log-stack">{{ modalLog.stackTrace }}</pre>
          </div>
        </div>
      </AModal>
    </div>
  </div>
</template>

<style>
:root {
  --success-color: #52c41a;
  --warning-color: #faad14;
  --error-color: #f5222d;
  --info-color: #1890ff;
  --primary-bg: #23272f;
  --secondary-bg: #2c313c;
  --log-border-radius: 6px;
  --log-font: 'JetBrains Mono', 'Fira Code', 'Source Code Pro', Consolas, monospace;
  --log-container-bg: #fff;
  --log-container-color: #23272f;
}

/* Ant Design 组件样式覆盖 */
:deep(.ant-card) {
  background: var(--primary-bg);
}

:deep(.log-card-container) {
  height: 100%;
}

/* 合并多个 Ant Card Body 样式覆盖 */
:deep(.ant-card .ant-card-body),
:deep(.log-card-container .ant-card-body),
:where(.css-dev-only-do-not-override-19kkpcr).ant-card .ant-card-body {
  padding: 4px !important;
  height: 100% !important;
  display: flex !important;
  flex-direction: column !important;
  margin: 0 !important;
  border: none !important;
}

/* 日志容器样式 */
.log-container {
  font-family: var(--log-font);
  font-size: 13px;
  line-height: 1.5;
  height: 100%;
  overflow-y: auto;
  background: var(--log-container-bg, var(--secondary-bg, #2c313c));
}

/* 日志项样式 */
.log-item {
  display: flex;
  align-items: center;
  margin-bottom: 1px;
  padding: 2px 2px;
  border-left: 3px solid transparent;
  background: var(--log-item-bg, rgba(255, 255, 255, 0.02));
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
  transition: background 0.2s;
  white-space: nowrap;
  font-size: 10px;
  border-radius: 2px;
  gap: 5px;
}

.log-time {
  color: #8c8c8c;
  font-size: 12px;
  min-width: 140px;
  max-width: 140px;
  text-align: left;
  display: inline-block;
  flex-shrink: 0;
}

.log-level {
  min-width: 60px;
  max-width: 60px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-weight: bold;
  padding: 0 6px;
  border-radius: 4px;
  color: #fff;
  box-sizing: border-box;
  flex-shrink: 0;
  font-size: 10px;
}

.log-class {
  color: #bfbfbf;
  max-width: 180px;
  min-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: left;
  display: inline-block;
  flex-shrink: 0;
  margin-right: 8px;
}

.log-content {
  color: var(--log-container-color, #23272f);
  word-break: break-all;
  white-space: pre;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: left;
  display: inline-block;
}

/* 日志级别样式 */
.log-item-info {
  border-left-color: rgb(var(--primary-color) / var(--un-bg-opacity));
}

.log-item-info:hover,
.log-item-warn:hover,
.log-item-error:hover,
.log-item-debug:hover {
  cursor: pointer;
}

.log-item-info:hover {
  background: rgba(24, 144, 255, 0.12);
}

.log-item-warn {
  border-left-color: var(--warning-color);
}

.log-item-warn:hover {
  background: rgba(250, 173, 20, 0.16);
}

.log-item-error {
  border-left-color: var(--error-color);
}

.log-item-error:hover {
  background: rgba(245, 34, 45, 0.16);
}

.log-item-debug {
  border-left-color: var(--success-color);
}

.log-item-debug:hover {
  background: rgba(82, 196, 26, 0.13);
}

.level-info,
.level-warn,
.level-error,
.level-debug {
  min-width: 60px;
  display: inline-block;
  text-align: center;
}

.level-info {
  color: rgb(var(--primary-color) / var(--un-bg-opacity));
}

.level-warn {
  color: var(--warning-color);
}

.level-error {
  color: var(--error-color);
}

.level-debug {
  color: var(--success-color);
}

/* 模态框样式 */
.modal-log-detail {
  background: var(--modal-bg, #23272f);
  border-radius: 8px;
  padding: 16px 20px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
  border: 1px solid var(--modal-border, #2c313c);
}

.modal-log-row {
  display: flex;
  align-items: flex-start;
  margin-bottom: 12px;
}

.modal-log-label {
  min-width: 60px;
  color: #aaa;
  font-weight: bold;
  margin-right: 8px;
}

/* 为级别标签添加适应内容长度的样式 */
.modal-log-value.level-tag {
  display: inline-block;
  max-width: fit-content;
  white-space: nowrap;
}

.modal-log-content {
  color: var(--modal-content-color, #e6e6e6);
  border-radius: 4px;
  margin: 0;
  font-family: var(--log-font);
  font-size: 13px;
  white-space: pre-wrap;
}

.modal-log-stack {
  color: #ff6b6b;
  background: #2a2a2a;
  border: 1px solid #444;
  border-radius: 4px;
  padding: 12px;
  margin: 0;
  font-family: var(--log-font);
  font-size: 12px;
  white-space: pre-wrap;
  max-height: 300px;
  overflow-y: auto;
  line-height: 1.4;
}

/* 级别标签样式 */
.level-tag {
  border-radius: 4px;
  padding: 2px 8px;
  font-weight: bold;
}

.level-tag.level-info {
  background: #1890ff22;
  color: #1890ff;
}

.level-tag.level-warn {
  background: #faad1422;
  color: #faad14;
}

.level-tag.level-error {
  background: #f5222d22;
  color: #f5222d;
}

.level-tag.level-debug {
  background: #52c41a22;
  color: #52c41a;
}

/* 暗色主题样式 */
.dark {
  --log-container-bg: #23272f;
  --log-container-color: #fff;
}

/* 页面布局样式 */
.log-page-wrapper {
  position: relative;
  height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.log-management-container {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  padding: 8px 0px 0px 0px;
}

.filter-section-fixed {
  position: relative;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  margin: 0;
  padding: 12px;
  background: var(--ant-card-bg);
  border-bottom: 1px solid var(--ant-border-color-split);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  flex-shrink: 0;
}

.dark .filter-section-fixed {
  background: #1f1f1f;
  border-bottom-color: #303030;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}

.log-card-container {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: auto;
}

/* 筛选区域样式 */
.filter-row {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-bottom: 8px;
}

.filter-row:last-child {
  margin-bottom: 0;
}

.filter-actions {
  display: flex;
  gap: 8px;
  margin-left: auto;
}

/* 筛选器样式 */
.node-select {
  width: 160px;
}

.level-select {
  width: 100px;
}

.logger-select {
  min-width: 200px;
  max-width: 500px;
}

.keyword-select {
  width: 250px;
}

.date-picker {
  width: 160px;
}

/* 位置信息样式 */
.modal-log-location {
  font-family: var(--log-font);
  font-size: 13px;
}

.location-class {
  color: #52c41a;
  font-weight: bold;
}

.location-method {
  color: #1890ff;
  font-weight: 500;
}

.location-line {
  color: #faad14;
  font-weight: 500;
}
</style>
